﻿using System;
using System.Collections.Generic;
using System.Threading;
using StockTrader.Core;
using StockTrader.Platform.Logging;

namespace StockTrader.Utilities.Broker
{
    public class BrokerUtils
    {
        public static BrokerErrorCode GetDerivativeQuote(IBroker broker, DerivativeSymbolQuoteToGet dqg)
        {
            DerivativeSymbolQuote dqi = null;
            return broker.GetDerivativeQuote(dqg.Symbol, dqg.InstrumentType, dqg.ExpiryDate, dqg.StrikePrice, out dqi);
        }

        public static BrokerErrorCode CheckDerivativeOrderbook(IBroker broker, DateTime from, DateTime to)
        {
            Dictionary<string, DerivativeOrderBookRecord> orders = null;
            BrokerErrorCode errorCode = BrokerErrorCode.Success;
            errorCode = broker.GetDerivativesOrderBook(from, to, InstrumentType.OptionCallIndex, false, false, out orders);

            orders = null;

            errorCode |= broker.GetDerivativesOrderBook(from, to, InstrumentType.FutureIndex, false, false, out orders);

            return errorCode;
        }

        public static BrokerErrorCode CheckDerivativeTradebook(IBroker broker, DateTime from, DateTime to)
        {
            Dictionary<string, DerivativeTradeBookRecord> trades = null;
            BrokerErrorCode errorCode = BrokerErrorCode.Success;
            errorCode = broker.GetDerivativesTradeBook(from, to, InstrumentType.OptionCallIndex, false, out trades);

            trades = null;

            errorCode |= broker.GetDerivativesTradeBook(from, to, InstrumentType.FutureIndex, false, out trades);

            return errorCode;
        }

        public static void PollDerivativeTradeAndOrderbookContinuously(object obj)
        {
            // Successful login, now do the dance
            BrokingAccountObject brokerAccountObj = (BrokingAccountObject)obj;
            IBroker iciciDirectAccount = brokerAccountObj.Broker;

            DateTime from = DateTime.Now.AddDays(-1);
            DateTime to = DateTime.Now;

            while (!brokerAccountObj.DoStopThread)
            {
                BrokerErrorCode errorCode = BrokerErrorCode.Success;
                string traceString = string.Empty;

                errorCode = CheckDerivativeTradebook(iciciDirectAccount, from, to);
                traceString = "Periodic tradebook check: " + errorCode.ToString() + "\n";

                errorCode = CheckDerivativeOrderbook(iciciDirectAccount, from, to);
                traceString += "Periodic orderbook check: " + errorCode.ToString();

                FileTracing.TraceOut(traceString);

                // sleep of 3 minutes
                Thread.Sleep(1000 * 60 * 3);
            }    
        }

        public static void GetDerivativeQuoteContinuously(object obj)
        {
            BrokingAccountObject brokerAccountObj = (BrokingAccountObject)obj;
            DerivativeSymbolQuoteToGet dqg = (DerivativeSymbolQuoteToGet)brokerAccountObj.CustomData;

            IBroker iciciDirectAccount = brokerAccountObj.Broker;

            while (!brokerAccountObj.DoStopThread)
            {
                BrokerErrorCode errorCode = BrokerErrorCode.Success;
                
                errorCode = GetDerivativeQuote(iciciDirectAccount, dqg);
                
                Thread.Sleep(1000 * 5);
            }
        }

        // Helper function to cancel stock specific all outstanding orders and trace it out
        public static BrokerErrorCode CancelStockOutstandingOrdersAndTrace(IBroker broker, string stockCode)
        {
            Dictionary<string, BrokerErrorCode> cancelOrderErrCodes;
            BrokerErrorCode errorCode = broker.CancelAllOutstandingEquityOrders(stockCode, out cancelOrderErrCodes);
            string traceString = Thread.CurrentThread.Name + ": CancelStockAllOutstandingEquityOrders: " + errorCode.ToString() + "\n";
            foreach (KeyValuePair<string, BrokerErrorCode> errCodePair in cancelOrderErrCodes)
            {
                traceString += "Order: " + errCodePair.Key + ": Cancel status code is " + "\"" + errCodePair.Value.ToString() + "\"\n";
            }
            FileTracing.TraceOut(traceString);

            return errorCode;
        }

        // TODO: BUGBUGCD Need not have 2 GetEquityTradeBookToday (or GetEquityOrderBookToday) ,1 for stock specific, other for all stocks
        // but to avoid erroneous call by user, no harm in giving 2 wrappers specifically

        // Complete Order book for earliest valid day (usually used in "today" context)
        public static BrokerErrorCode GetEquityOrderBookToday(
            IBroker broker,
            bool newTradesOnly,
            bool bOnlyOutstandingOrders,
            string stockCode,
            out Dictionary<string, EquityOrderBookRecord> orders)
        {
            DateTime EarliestValidMarketOpenDate = MarketUtils.GetMarketCurrentDate();
            return broker.GetEquityOrderBook(EarliestValidMarketOpenDate, EarliestValidMarketOpenDate, newTradesOnly,
                bOnlyOutstandingOrders, stockCode, out orders);
        }

        // Filtered order book for earliest valid day (usually used in "today" context)
        public static BrokerErrorCode GetEquityOrderBookToday(
            IBroker broker,
            bool newTradesOnly,
            bool bOnlyOutstandingOrders,
            out Dictionary<string, EquityOrderBookRecord> orders)
        {
            DateTime EarliestValidMarketOpenDate = MarketUtils.GetMarketCurrentDate();
            return broker.GetEquityOrderBook(EarliestValidMarketOpenDate, EarliestValidMarketOpenDate, newTradesOnly,
                bOnlyOutstandingOrders, null, out orders);
        }

        // Get trade book for today
        public static BrokerErrorCode GetEquityTradeBookToday(IBroker broker,
            bool newTradesOnly,
            out Dictionary<string, EquityTradeBookRecord> trades)
        {
            DateTime today = DateTime.Now;
            return broker.GetEquityTradeBook(today, today, newTradesOnly, null, out trades);
        }

        // Get trade book for today for a particular stock
        public static BrokerErrorCode GetEquityTradeBookToday(IBroker broker,
            string stockCode,
            bool newTradesOnly,
            out Dictionary<string, EquityTradeBookRecord> trades)
        {
            DateTime today = DateTime.Now;
            return broker.GetEquityTradeBook(today, today, newTradesOnly, stockCode, out trades);
        }

    }
}
